﻿using MQTTClient.Model;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace MQTTClient.Bll
{
    public class UDPClientBll : UDPClientBase
    {
        /// <summary>
        /// 连接服务器
        /// </summary>
        public void ServerStart()
        {
            try
            {
                UdpState = new UdpState();
                udpClient = new UdpClient();
               // udpClient = new UdpClient(this.ClientProt);//指定客户端自己的端口
                udpClient.Client = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                ServerIPEndPoint = new IPEndPoint(IPAddress.Parse(this.ServerIP), this.ServerPort);
                //ClientIPEndPoint = new IPEndPoint(IPAddress.Any, 0);
                udpClient.Connect(this.ServerIPEndPoint); // 与服务器建立连接
               
                UdpState.udpClient = udpClient;
                //开始异步接收
                ReceiveMessages();
                string str = string.Format("UDP服务器连接成功！Ip:{0},端口{1}。", this.ServerIP, this.ServerPort);
                OnClientConnectd(ServerIPEndPoint, str);
            }
            catch (Exception e)
            {
                string str = string.Format("UDP服务器连接失败！Ip:{0},端口{1}。原因{2}。", this.ServerIP, this.ServerPort, e.Message);
                OnClientConnectd(ServerIPEndPoint, str);
            }

        }
        /// <summary>
        /// 断开服务器
        /// </summary>
        public void ServerClose()
        {
            try
            {
                udpClient.Client.Shutdown(SocketShutdown.Both);
                udpClient.Client.Close(1000);//n是秒数
                udpClient.Close();

                string str = string.Format("UDP服务器断开成功！Ip:{0},端口{1}。", this.ServerIP, this.ServerPort);
                udpClient = null;
                OnClientConnectd(ServerIPEndPoint, str);
            }
            catch (Exception e)
            {
                string str = string.Format("UDP服务器断开失败！Ip:{0},端口{1}。原因{2}。", this.ServerIP, this.ServerPort, e.Message);
                OnClientConnectd(ServerIPEndPoint, str);
            }

        }

        /// <summary>
        /// 开始发送数据
        /// </summary>
        /// <param name="mesgData"></param>
        public void BeginSendData(string mesgData)
        {
            try
            {
                if (CheckServerConnectd())//如果连接没有关闭或终止
                {
                    Byte[] sendBytes;
                    sendBytes = Encoding.UTF8.GetBytes(mesgData);
                    // 调用发送回调函数ServerIPEndPoint
                    //udpClient.BeginSend(sendBytes, sendBytes.Length,  ClientIPEndPoint, new AsyncCallback(SendCallback), UdpState);
                    udpClient.BeginSend(sendBytes, sendBytes.Length, new AsyncCallback(SendCallback), UdpState);

                    this.OnServerSendDatad(mesgData);
                }
                else
                {
                    ServerStart();
                    this.OnClientExceptiond("发送数据失败", "与服务器的连接已关闭或终止！");
                }
            }
            catch (Exception ex)
            {
                string str = "开始发送数据失败";
                this.OnClientExceptiond(str, ex);
            }
        }
        /// <summary>
        /// 检查服务器连接状态  
        /// </summary>
        private bool CheckServerConnectd()
        {
            if (!udpClient.Client.Poll(1000, SelectMode.SelectRead))
            {
                return true;
            }
            return false;
        }

        // 发送回调函数
        public void SendCallback(IAsyncResult iar)
        {
            try
            {
                UdpState udpState = iar.AsyncState as UdpState;
                lock (this)
                {
                    if (iar.IsCompleted)
                    {
                        Console.WriteLine("第{0}个发送完毕！", udpState.counter);
                        Console.WriteLine("number of bytes sent: {0}", udpState.udpClient.EndSend(iar));
                    }
                }
            }
            catch (Exception ex)
            {
                string str = "发送数据完成回调失败";
                this.OnClientExceptiond(str, ex);
            }
        }
        /// <summary>
        /// 开始接收数据
        /// </summary>
        public void ReceiveMessages()
        {
            try
            {
                lock (this)
                {
                    udpClient.BeginReceive(new AsyncCallback(ReceiveCallback), UdpState);
                }
            }
            catch (Exception ex)
            {
                string str = "开始接收数据失败";
                this.OnClientExceptiond(str, ex);
            }
        }
        /// <summary>
        /// 接收回调函数
        /// </summary>
        /// <param name="iar"></param>
        public void ReceiveCallback(IAsyncResult iar)
        {
            try
            {
                UdpState udpState = iar.AsyncState as UdpState;

                if (iar.IsCompleted)
                {
                    if (udpState.udpClient.Client != null)
                    {
                        Byte[] receiveBytes = udpState.udpClient.EndReceive(iar, ref UdpState.IpEndPoint);
                        string mesgData = Encoding.UTF8.GetString(receiveBytes);
                        // Console.WriteLine("Received: {0}", receiveString);
                        this.OnServerReceived(mesgData);
                        ReceiveMessages();
                    }
                }
            }
            catch (System.Net.Sockets.SocketException e)
            {
                if (e.Message.Contains("远程主机强迫关闭了一个现有的连接。"))
                {
                    ServerStart();
                }
            }
            catch (Exception ex)
            {             
                string str = "接收数据完成回调失败";
                this.OnClientExceptiond(str, ex);
            }
        }
    }
}
